home *** CD-ROM | disk | FTP | other *** search
- /* net/rom user command processing
- * Copyright 1989 by Daniel M. Frank, W9NK. Permission granted for
- * non-commercial distribution only.
- */
- /* Mods by G1EMM, PA0GRI and WG7J */
-
- #include "global.h"
- #ifdef NETROM
- #include "ctype.h"
- #include "commands.h"
- #include "mbuf.h"
- #include "ax25.h"
- #include "mailbox.h"
- #include "netrom.h"
- #include "pktdrvr.h"
- #include "files.h"
- #ifndef MSDOS
- #include "session.h"
- #endif
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: nrcmd.c,v 1.22 1997/09/07 21:18:28 root Exp root $";
- #endif
-
- /*lint -esym(534,pax25) */
- static int Nr_hidden = 1;
- static unsigned Nr_sorttype = 1;
- char Nr4user[AXALEN];
- extern unsigned Nr_sorttype;
- extern int Nr_derate;
- extern int Nr_promisc;
- extern unsigned Nr_timertype;
-
-
- const char *Nr4states[] =
- {
- "Disconnected",
- "Conn Pending",
- "Connected",
- "Disc Pending",
- "Listening"
- };
-
- const char *Nr4reasons[] =
- {
- "Normal",
- "By Peer",
- "Timeout",
- "Reset",
- "Refused"
- };
-
- static void nodetickproc (int, void *, void *);
- static int dobcnodes (int argc, char *argv[], void *p);
- static int dobcpoll (int argc, char *argv[], void *p);
- static int dointerface (int argc, char *argv[], void *p);
- static int donfadd (int argc, char *argv[], void *p);
- static int donfdrop (int argc, char *argv[], void *p);
- static int donfdump (void);
- static int donfmode (int argc, char *argv[], void *p);
- static int donodefilter (int argc, char *argv[], void *p);
- static int donodetimer (int argc, char *argv[], void *p);
- static int donracktime (int argc, char *argv[], void *p);
- static int donrmycall (int argc, char *argv[], void *p);
- static int donrchoketime (int argc, char *argv[], void *p);
- static int donrconnect (int argc, char *argv[], void *p);
- static int donrirtt (int argc, char *argv[], void *p);
- static int donrkick (int argc, char *argv[], void *p);
- static int dorouteadd (int argc, char *argv[], void *p);
- static int doroutedrop (int argc, char *argv[], void *p);
- static int donrqlimit (int argc, char *argv[], void *p);
- static int donrreset (int argc, char *argv[], void *p);
- static int donrretries (int argc, char *argv[], void *p);
- int donrroute (int argc, char *argv[], void *p);
- int donrstatus (int argc, char *argv[], void *p);
- static int donrsave (int argc, char *argv[], void *p);
- static int donrload (int argc, char *argv[], void *p);
- static int donrttl (int argc, char *argv[], void *p);
- static int donruser (int argc, char *argv[], void *p);
- static int donrwindow (int argc, char *argv[], void *p);
- void doobsotick (void);
- static int doobsotimer (int argc, char *argv[], void *p);
- static int dominquality (int argc, char *argv[], void *p);
- static int donrtype (int argc, char *argv[], void *p);
- static int donrpromisc (int argc, char *argv[], void *p);
- static int donrderate (int argc, char *argv[], void *p);
- static int doroutesort (int argc, char *argv[], void *p);
- static int donrhidden (int argc, char *argv[], void *p);
- static void doallinfo (void);
- static struct iface *FindNrIface (char *name);
-
- int donrneighbour (int argc, char *argv[], void *p);
-
- extern int donr4tdisc (int argc, char *argv[], void *p);
- extern struct nr_bind *find_best (struct nr_bind * list, unsigned obso);
- extern void nrresetlinks (struct nrroute_tab *rp);
-
- static struct cmds Nrcmds[] =
- {
- { "acktime", donracktime, 0, 0, NULLCHAR },
- { "alias", donralias, 0, 0, NULLCHAR },
- { "bcnodes", dobcnodes, 0, 2, "netrom bcnodes <iface>" },
- { "bcpoll", dobcpoll, 0, 2, "netrom bcpoll <iface>" },
- #ifdef ALLSESSIONS
- { "connect", donrconnect, 1024, 2, "netrom connect <node>" },
- #endif
- { "call", donrmycall, 0, 0, NULLCHAR },
- { "choketime", donrchoketime, 0, 0, NULLCHAR },
- { "derate", donrderate, 0, 0, NULLCHAR },
- { "hidden", donrhidden, 0, 0, NULLCHAR },
- { "interface", dointerface, 0, 0, NULLCHAR },
- { "irtt", donrirtt, 0, 0, NULLCHAR },
- { "kick", donrkick, 0, 2, "netrom kick <&nrcb>" },
- { "load", donrload, 0, 0, NULLCHAR },
- { "minquality", dominquality, 0, 0, NULLCHAR },
- { "neighbour", donrneighbour, 0, 0, NULLCHAR },
- { "nodefilter", donodefilter, 0, 0, NULLCHAR },
- { "nodetimer", donodetimer, 0, 0, NULLCHAR },
- { "obsotimer", doobsotimer, 0, 0, NULLCHAR },
- { "promiscuous", donrpromisc, 0, 0, NULLCHAR },
- { "qlimit", donrqlimit, 0, 0, NULLCHAR },
- { "route", donrroute, 0, 0, NULLCHAR },
- { "reset", donrreset, 0, 2, "netrom reset <&nrcb>" },
- { "retries", donrretries, 0, 0, NULLCHAR },
- { "status", donrstatus, 0, 0, NULLCHAR },
- { "save", donrsave, 0, 0, NULLCHAR },
- #if defined(ALLSESSIONS) && defined(ALLSERV)
- { "split", donrconnect, 1024, 2, "netrom split <node>" },
- #endif
- { "timertype", donrtype, 0, 0, NULLCHAR },
- { "ttl", donrttl, 0, 0, NULLCHAR },
- #ifdef NR4TDISC
- { "tdisc", donr4tdisc, 0, 0, NULLCHAR },
- #endif
- { "user", donruser, 0, 0, NULLCHAR },
- { "window", donrwindow, 0, 0, NULLCHAR },
- { NULLCHAR, NULL, 0, 0, NULLCHAR }
- };
-
-
- struct timer Nodetimer; /* timer for nodes broadcasts */
- struct timer Obsotimer; /* timer for aging routes */
-
-
- /* Command multiplexer */
- int
- donetrom (int argc, char *argv[], void *p)
- {
- return subcmd (Nrcmds, argc, argv, p);
- }
-
-
- static struct cmds Routecmds[] =
- {
- { "add", dorouteadd, 0, 6, "netrom route add <alias> <destination> <interface> <quality> <neighbor>" },
- { "drop", doroutedrop, 0, 4, "netrom route drop <destination> <neighbor> <interface>" },
- { "info", dorouteinfo, 0, 0, NULLCHAR },
- { "sort", doroutesort, 0, 1, NULLCHAR },
- { NULLCHAR, NULL, 0, 0, NULLCHAR }
- };
-
-
- /* Route command multiplexer */
- int
- donrroute (int argc, char *argv[], void *p)
- {
- if (argc < 2) {
- (void) doroutedump ();
- return 0;
- }
- return subcmd (Routecmds, argc, argv, p);
- }
-
-
- /* Code to sort Netrom node listing
- * D. Crompton 2/92
- * Dump a list of known netrom routes in
- * sorted order determined by sort
- * flag - default = sort by alias
- */
-
- int
- doroutedump ()
- {
- register struct nrroute_tab *rp;
- register int i, j, k, column;
- char buf[17];
- char *cp, *temp;
-
- column = 1;
-
- for (i = 0, j = 0; i < NRNUMCHAINS; i++)
- for (rp = Nrroute_tab[i]; rp != NULLNRRTAB; j++, rp = rp->next) ;
-
- #define RTSIZE 17
-
- if (j) {
- /* Allocate maximum size */
- temp = mallocw ((unsigned) j * RTSIZE);
-
- for (i = 0, j = 0, k = 0; i < NRNUMCHAINS; i++)
- for (rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next) {
- if (!Nr_hidden && *rp->alias == '#')
- continue;
- if (Nr_sorttype) {
- strncpy (buf, rp->alias, 17);
- /* remove trailing spaces */
- if ((cp = strchr (buf, ' ')) == NULLCHAR)
- cp = &buf[strlen (buf)];
- if (cp != buf) /* don't include colon for null alias */
- *cp++ = ':';
- pax25 (cp, rp->call);
- } else {
- pax25 (buf, rp->call);
- cp = &buf[strlen (buf)];
- *cp++ = ':';
- strcpy (cp, rp->alias);
- }
- sprintf (&temp[k], "%-16.16s", buf);
- k += RTSIZE;
- j++; /* number actually shown */
- }
-
- qsort (temp, (size_t) j, RTSIZE, (int (*)(const void *, const void *)) strcmp);
-
- for (i = 0, k = 0; i < j; i++, k += RTSIZE) {
- tprintf ("%-16s ", &temp[k]);
- if (column++ == 4) {
- if (tputc ('\n') == EOF) {
- free (temp);
- return 0;
- }
- column = 1;
- }
- }
-
- if (column != 1)
- tputc ('\n');
- free (temp);
- }
- return 0;
- }
-
-
- /* netrom Route Dump Sort - ALIAS or CALL first */
- static int
- doroutesort (int argc, char *argv[], void *p OPTIONAL)
- {
- if (argc < 2) {
- tprintf ("Netrom Sort by %s\n", Nr_sorttype ? "Alias" : "Call");
- return 0;
- }
- switch (argv[1][0]) {
- case 'A':
- case 'a':
- Nr_sorttype = 1;
- break;
- case 'C':
- case 'c':
- Nr_sorttype = 0;
- break;
- default:
- tputs ("usage: netrom sort [alias|call]\n");
- return -1;
- }
-
- return 0;
- }
-
-
- /* Print detailed information on ALL routes (sorted) */
- /* D. Crompton */
- static void
- doallinfo ()
- {
- register struct nrroute_tab *rp;
- register struct nr_bind *bp;
- register struct nrnbr_tab *np;
- char neighbor[AXBUF];
- char buf[17];
- char *cp, *temp;
- int i, j, k, flow_tmp;
-
- flow_tmp = Current->flowmode;
- Current->flowmode = 1;
-
- for (i = 0, j = 0; i < NRNUMCHAINS; i++)
- for (rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next)
- for (bp = rp->routes; bp != NULLNRBIND; bp = bp->next, j++) ;
-
- #define STRSIZE 72
-
- if (j) {
-
- temp = mallocw ((unsigned) j * STRSIZE);
-
- for (i = 0, k = 0; i < NRNUMCHAINS; i++)
- for (rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next)
- for (bp = rp->routes; bp != NULLNRBIND; bp = bp->next, k += STRSIZE) {
- np = bp->via;
- if (Nr_sorttype) {
-
- strncpy (buf, rp->alias, 17);
- if ((cp = strchr (buf, ' ')) == NULLCHAR)
- cp = &buf[strlen (buf)];
- if (cp != buf)
- *cp++ = ':';
- pax25 (cp, rp->call);
-
- } else {
-
- pax25 (buf, rp->call);
- cp = &buf[strlen (buf)];
- *cp++ = ':';
- strcpy (cp, rp->alias);
-
- }
-
- sprintf (&temp[k], "%-16s %3d %3d %-8s %-9s %c\n", buf,
- bp->quality, bp->obsocnt,
- np->iface->name,
- pax25 (neighbor, np->call),
- (bp->flags & NRB_PERMANENT ? 'P' :
- bp->flags & NRB_RECORDED ? 'R' : 'B'));
-
- }
- qsort (temp, (size_t) j, STRSIZE, (int (*)(const void *, const void *)) strcmp);
-
- for (i = 0, k = 0; i < j; i++, k += STRSIZE)
- if (tputs (&temp[k]) == EOF)
- break;
- free (temp);
- Current->flowmode = flow_tmp;
- }
- }
-
-
- /* Find the interface, and check if it is active for netrom */
- static struct iface *
- FindNrIface (char *name)
- {
- struct iface *ifp;
-
- if ((ifp = if_lookup (name)) == NULLIF) {
- tprintf (Badinterface, name);
- return NULLIF;
- }
- if (!(ifp->flags & IS_NR_IFACE)) {
- tprintf ("%s is not active for netrom\n", name);
- return NULLIF;
- }
- return ifp;
- }
-
-
- /* print detailed information on an individual route
- * Shows alias as well - WG7J
- */
- int
- dorouteinfo (int argc, char *argv[], void *p OPTIONAL)
- {
- char *cp;
- register struct nrroute_tab *rp;
- register struct nrroute_tab *npp;
- struct nr_bind *bp;
- struct nrnbr_tab *np;
- char destbuf[AXBUF];
- char neighbor[AXBUF];
- char alias[AXALEN];
- char buf[AXALEN];
- char nb_alias[AXALEN];
- int print_header = 1;
- int16 rhash;
-
- if (argc == 1) {
- doallinfo ();
- return 0;
- }
- (void) putalias (alias, argv[1], 0);
- (void) strupr (argv[1]); /*make sure it's upper case*/
- if ((rp = find_nrboth (alias, argv[1])) == NULLNRRTAB) {
- /*no such call or node alias*/
- tputs ("no such node\n\n");
- return 0;
- }
- /*copy the real alias*/
- strncpy (buf, rp->alias, AXALEN);
- if ((cp = strchr (buf, ' ')) != NULLCHAR)
- *cp = '\0';
-
- for (bp = rp->routes; bp != NULLNRBIND; bp = bp->next) {
- np = bp->via;
- /* now we have to find the alias of the neighbour used
- * so we can print that as well!
- */
- rhash = nrhash (np->call);
- for (npp = Nrroute_tab[rhash]; npp != NULLNRRTAB; npp = npp->next)
- if (addreq (npp->call, np->call))
- break;
- if (npp == NULLNRRTAB)
- continue;
- /* found, now remove trailing spaces */
- strcpy (nb_alias, npp->alias);
- if ((cp = strchr (nb_alias, ' ')) != NULLCHAR)
- *cp = '\0';
- if (print_header) {
- print_header = 0;
- tputs (" Node Neighbour Port PQual Obsocnt Type\n");
- tprintf ("%6s:%-9s ", buf, pax25 (destbuf, rp->call));
- } else
- tputs (" ");
- tprintf ("%6s:%-9s %-5s %3d %d %c\n",
- nb_alias, pax25 (neighbor, np->call),
- np->iface->name,
- bp->quality, bp->obsocnt,
- bp->flags & NRB_PERMANENT ? 'P' : \
- (bp->flags & NRB_RECORDED ? 'R' : 'B'));
- }
- tputc ('\n');
- return 0;
- }
-
-
- int
- donrneighbour (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- int i, printheader = 1;
- struct nrnbr_tab *np;
- struct nrroute_tab *rp;
- struct nr_bind *thebind;
- int16 rhash;
- int justused;
- char tmp[AXBUF];
- char alias[AXALEN];
- char *cp;
- int quality = 0;
- int obsocnt = 0;
-
- for (i = 0; i < NRNUMCHAINS; i++) /*loop through all chains of neighbours*/
- for (np = Nrnbr_tab[i]; np != NULLNTAB; np = np->next) {
- /* If the interface is hidden, then do not show the route */
- /*
- if(np->iface->flags & HIDE_PORT && Curproc->input != Command->input)
- continue;
- */
- if (printheader) {
- tputs ("Routes :\n Neighbour Port PQual Obsocnt Dest\n");
- printheader = 0;
- }
- /* has this one been used recently ? */
- if ((secclock () - np->lastsent) < 60)
- justused = 1;
- else
- justused = 0;
-
- /* now we have to find the alias of this neighbour
- * so we can print that as well!
- */
- rhash = nrhash (np->call);
- for (rp = Nrroute_tab[rhash]; rp != NULLNRRTAB; rp = rp->next)
- if (addreq (rp->call, np->call))
- break;
-
- if (rp != NULLNRRTAB) {
- /* found, now remove trailing spaces */
- strcpy (alias, rp->alias);
- if ((cp = strchr (alias, ' ')) != NULLCHAR)
- *cp = '\0';
- /*find the quality for this neighbour*/
- thebind = find_best (rp->routes, 1);
- if (thebind) {
- quality = (int) thebind->quality;
- obsocnt = (int) thebind->obsocnt;
- } else /* this shouldn't happen */
- quality = obsocnt = 0;
- } else
- strcpy (alias, "##temp");
-
- /* print it all out */
- tprintf ("%s %6s:%-9s %-5s %4d %1d %3d\n",
- (justused) ? ">" : " ",
- alias, pax25 (tmp, np->call),
- np->iface->name,
- quality, obsocnt, np->refcnt);
- }
- if (!printheader)
- tputc ('\n');
- return 0;
- }
-
-
- /* define the netrom call,
- * this simply changes the interface linkaddress!
- * but is a little easier to use...
- */
- static int
- donrmycall (int argc, char *argv[], void *p OPTIONAL)
- {
- char tmp[AXBUF];
-
- if (Nr_iface == NULLIF) {
- tputs ("Attach netrom interface first\n");
- return 1;
- }
- if (argc < 2) {
- if (Nr_iface->hwaddr == NULLCHAR)
- tputs ("not set\n");
- else
- tprintf ("%s\n", pax25 (tmp, Nr_iface->hwaddr));
- } else {
- if (strlen (argv[1]) > (AXBUF - 1)) {
- tputs ("too long\n");
- return 1;
- }
- if (Nr_iface->hwaddr != NULLCHAR)
- free (Nr_iface->hwaddr);
- Nr_iface->hwaddr = mallocw ((unsigned) Nr_iface->iftype->hwalen);
- (void) (*Nr_iface->iftype->scan) (Nr_iface->hwaddr, argv[1]);
- #ifdef MAILBOX
- setmbnrid ();
- #endif
- }
- return 0;
- }
-
-
- /* make an interface available to net/rom */
- /* arguments are:
- * argv[0] - "interface"
- * argv[1] - "iface" , the interface name
- * argv[2] - "quality", the interface broadcast quality
- * argv[3] - "n" or "v", to override the default (verbose)
- * n = never broadcast verbose
- * v = always broadcast verbose
- */
- static
- int
- dointerface (int argc, char *argv[], void *p OPTIONAL)
- {
- register struct iface *ifp;
- int i, mtu;
-
- if (Nr_iface == NULLIF) {
- tputs ("Attach netrom interface first\n");
- return 1;
- }
- if (argc < 3) {
- i = 0;
- for (ifp = Ifaces; ifp; ifp = ifp->next) {
- if (ifp->flags & IS_NR_IFACE) {
- if (!i) {
- i = 1;
- tputs ("Iface Qual Verbose\n");
- }
- tprintf ("%-6s %-3d %c\n",
- ifp->name, ifp->quality,
- (ifp->flags & NR_VERBOSE) ? 'Y' : 'N');
- }
- }
- return 0;
- }
- if ((ifp = if_lookup (argv[1])) == NULLIF) {
- tprintf (Badinterface, argv[1]);
- return 1;
- }
- if (ifp->type != CL_AX25) {
- tprintf ("Interface %s is not NETROM compatible\n", argv[1]);
- return 1;
- }
-
- if (!strcasecmp (argv[2], "off")) {
- ifp->flags &= ~IS_NR_IFACE;
- return 0;
- }
-
- /* activate the interface */
- ifp->flags |= IS_NR_IFACE;
-
- /* set quality */
- if ((ifp->quality = atoi (argv[2])) > 255) /*Maximum quality possible*/
- ifp->quality = 255;
- /*check to see if quality is not 0 */
- if (ifp->quality <= 0)
- ifp->quality = 1;
-
- /* default is none-verbose */
- ifp->flags &= ~NR_VERBOSE;
- if (argc > 3)
- if (*argv[3] == 'v')
- ifp->flags |= NR_VERBOSE;
-
- /* Check, and set the NETROM MTU - WG7J */
- if ((mtu = ifp->ax25->paclen - 20) < Nr_iface->mtu)
- Nr_iface->mtu = (int16) mtu;
-
- /* Poll other nodes on this interface */
- nr_bcpoll (ifp);
-
- return 0;
- }
-
-
- /* convert a null-terminated alias name to a blank-filled, upcased */
- /* version. Return -1 on failure. */
- int
- putalias (register char *to, register char *from, int complain)
- {
- int len, i;
-
- if (!to || !from) {
- if (complain)
- tputs ("alias or call invalid\n");
- return -1;
- }
- if ((len = (int) strlen (from)) > ALEN) {
- if (complain)
- tputs ("alias too long - six characters max\n");
- return -1;
- }
- for (i = 0; i < ALEN; i++) {
- if (i < len) {
- if (islower (*from))
- *to++ = (char) toupper (*from++);
- else
- *to++ = *from++;
- } else
- *to++ = ' ';
- }
-
- *to = '\0';
- return 0;
- }
-
-
- /* Add a route */
- static int
- dorouteadd (int argc, char *argv[], void *p OPTIONAL)
- {
- char alias[AXALEN];
- char dest[AXALEN];
- unsigned quality;
- char neighbor[AXALEN];
- struct iface *ifp;
- int naddr;
-
- /* format alias (putalias prints error message if necessary) */
- if (putalias (alias, argv[1], 1) == -1)
- return -1;
-
- /* format destination callsign */
- if (setcall (dest, argv[2]) == -1) {
- tputs ("bad destination callsign\n");
- return -1;
- }
- /* find interface */
- if ((ifp = FindNrIface (argv[3])) == NULLIF) {
- return -1;
- }
- /* get and check quality value */
- if ((quality = (unsigned int) atoi (argv[4])) > 255) {
- tputs ("maximum route quality is 255\n");
- return -1;
- }
- /* Change from 871225 -- no digis in net/rom table */
- naddr = argc - 5;
- if (naddr > 1) {
- tputs ("Use the ax25 route command to specify digipeaters\n");
- return -1;
- }
- /* format neighbor address string */
- (void) setcall (neighbor, argv[5]);
-
- return nr_routeadd (alias, dest, ifp, quality, neighbor, 1, 0);
- }
-
-
- /* drop a route */
- static int
- doroutedrop (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- char dest[AXALEN], neighbor[AXALEN];
- struct iface *ifp;
-
- /* format destination and neighbor callsigns */
- if (setcall (dest, argv[1]) == -1) {
- tputs ("bad destination callsign\n");
- return -1;
- }
- if (setcall (neighbor, argv[2]) == -1) {
- tputs ("bad neighbor callsign\n");
- return -1;
- }
- /* find interface */
- if ((ifp = FindNrIface (argv[3])) == NULLIF)
- return -1;
-
- return nr_routedrop (dest, neighbor, ifp);
- }
-
-
- /* Broadcast nodes list on named interface. */
- static int
- dobcnodes (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- struct iface *ifp;
-
- /* find interface */
- if ((ifp = FindNrIface (argv[1])) == NULLIF)
- return -1;
-
- nr_bcnodes (ifp);
- return 0;
- }
-
-
- /* Poll nodes for routes on named interface. - WG7J */
- static int
- dobcpoll (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- struct iface *ifp;
-
- /* find interface */
- if ((ifp = FindNrIface (argv[1])) == NULLIF)
- return -1;
-
- nr_bcpoll (ifp);
- return 0;
- }
-
-
- /* Set outbound node broadcast interval */
- static int
- donodetimer (int argc, char *argv[], void *p OPTIONAL)
- {
- if (argc < 2) {
- tprintf ("Nodetimer %lu/%lu seconds\n",
- read_timer (&Nodetimer) / 1000L,
- dur_timer (&Nodetimer) / 1000L);
- return 0;
- }
- stop_timer (&Nodetimer);/* in case it's already running */
- Nodetimer.func = (void (*)(void *)) donodetick; /* what to call on timeout */
- Nodetimer.arg = NULLCHAR; /* dummy value */
- set_timer (&Nodetimer, atoi (argv[1]) * 1000L); /* set timer duration */
- start_detached_timer (&Nodetimer); /* and fire it up */
- return 0;
- }
-
-
- /* nodetickproc is the old donodetick. But, since it can call kpause, which is
- * very very bad for timer functions :-( this has been converted to a server.
- */
- void
- donodetick ()
- {
- if (newproc ("NETROM broadcast", 2048, nodetickproc, 0, NULL, NULL, 0) == NULLPROC)
- log (-1, "Couldn't start NETROM broadcast process");
-
- }
-
- static void
- nodetickproc (int i OPTIONAL, void *v1 OPTIONAL, void *v2 OPTIONAL)
- {
- struct iface *ifp;
-
- for (ifp = Ifaces; ifp; ifp = ifp->next) {
- if (ifp->flags & IS_NR_IFACE)
- nr_bcnodes (ifp);
- /* we want to delay after VERBOSE NETROM interfaces (except the last one) */
- if ((ifp->flags & NR_VERBOSE) && (ifp->next))
- (void) kpause (5000); /* this is needed to keep things hopping */
- }
-
- /* Restart timer */
- start_detached_timer (&Nodetimer);
- }
-
-
- /* Set timer for aging routes */
- static int
- doobsotimer (int argc, char *argv[], void *p OPTIONAL)
- {
- if (argc < 2) {
- tprintf ("Obsotimer %lu/%lu seconds\n",
- read_timer (&Obsotimer) / 1000L,
- dur_timer (&Obsotimer) / 1000L);
- return 0;
- }
- stop_timer (&Obsotimer);/* just in case it's already running */
- Obsotimer.func = (void (*)(void *)) doobsotick; /* what to call on timeout */
- Obsotimer.arg = NULLCHAR; /* dummy value */
- set_timer (&Obsotimer, atoi (argv[1]) * 1000L); /* set timer duration */
- start_detached_timer (&Obsotimer); /* and fire it up */
- return 0;
- }
-
-
- /* Go through the routing table, reducing the obsolescence count of
- * non-permanent routes, and purging them if the count reaches 0
- */
- void
- doobsotick ()
- {
- register struct nrnbr_tab *np;
- register struct nrroute_tab *rp, *rpnext;
- register struct nr_bind *bp, *bpnext;
- int i;
-
- for (i = 0; i < NRNUMCHAINS; i++) {
- for (rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rpnext) {
- rpnext = rp->next; /* save in case we free this route */
- /* Check all bindings for this route */
- for (bp = rp->routes; bp != NULLNRBIND; bp = bpnext) {
- bpnext = bp->next; /* in case we free this binding */
- if (bp->flags & NRB_PERMANENT) /* don't age these */
- continue;
- if (--bp->obsocnt == 0) { /* time's up! */
- if (bp->next != NULLNRBIND)
- bp->next->prev = bp->prev;
- if (bp->prev != NULLNRBIND)
- bp->prev->next = bp->next;
- else
- rp->routes = bp->next;
- rp->num_routes--; /* one less binding */
- np = bp->via; /* find the neighbor */
- free ((char *) bp); /* now we can free the bind */
- /* Check to see if we can free the neighbor */
- if (--np->refcnt == 0) {
- if (np->next != NULLNTAB)
- np->next->prev = np->prev;
- if (np->prev != NULLNTAB)
- np->prev->next = np->next;
- else {
- Nrnbr_tab[nrhash (np->call)] = np->next;
- }
- free ((char *) np); /* free the storage */
- }
- }
- }
- if (rp->num_routes == 0) { /* did we free them all? */
- if (rp->next != NULLNRRTAB)
- rp->next->prev = rp->prev;
- if (rp->prev != NULLNRRTAB)
- rp->prev->next = rp->next;
- else
- Nrroute_tab[i] = rp->next;
- /* No more routes left !
- * We should close/reset any netrom connections
- * still idling for this route ! - WG7J
- */
- nrresetlinks (rp);
- free ((char *) rp);
- }
- }
- }
-
- start_detached_timer (&Obsotimer);
- }
-
-
- static struct cmds Nfcmds[] =
- {
- { "add", donfadd, 0, 3, "netrom nodefilter add <neighbor> <interface> [quality]" },
- { "drop", donfdrop, 0, 3, "netrom nodefilter drop <neighbor> <interface>" },
- { "mode", donfmode, 0, 0, NULLCHAR },
- { NULLCHAR, NULLFP ((int, char **, void *)),0, 0, "nodefilter subcommands: add drop mode" }
- };
-
-
- /* nodefilter command multiplexer */
- static int
- donodefilter (int argc, char *argv[], void *p)
- {
- if (argc < 2) {
- (void) donfdump ();
- return 0;
- }
- return subcmd (Nfcmds, argc, argv, p);
- }
-
-
- /* display a list of <callsign,interface> pairs from the filter
- * list.
- */
- static int
- donfdump ()
- {
- int i, column = 1;
- struct nrnf_tab *fp;
- char buf[AXBUF];
-
- for (i = 0; i < NRNUMCHAINS; i++)
- for (fp = Nrnf_tab[i]; fp != NULLNRNFTAB; fp = fp->next) {
- pax25 (buf, fp->neighbor);
- tprintf ("%-7s %-8s %-3d ",
- buf, fp->iface->name, fp->quality);
- if (column++ == 3) {
- if (tputc ('\n') == EOF)
- return 0;
- column = 1;
- }
- }
-
- if (column != 1)
- tputc ('\n');
-
- return 0;
- }
-
-
- /* add an entry to the filter table */
- static int
- donfadd (int argc, char *argv[], void *p OPTIONAL)
- {
- struct iface *ifp;
- unsigned qual;
- char neighbor[AXALEN];
-
- /* format callsign */
- if (setcall (neighbor, argv[1]) == -1) {
- tputs ("bad neighbor callsign\n");
- return -1;
- }
- /* find interface */
- if ((ifp = FindNrIface (argv[2])) == NULLIF)
- return -1;
-
- qual = (unsigned int) ifp->quality; /* set default quality */
-
- if (argc > 3)
- qual = (unsigned int) atoi (argv[3]);
-
- return nr_nfadd (neighbor, ifp, qual);
- }
-
-
- /* drop an entry from the filter table */
- static int
- donfdrop (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- struct iface *ifp;
- char neighbor[AXALEN];
-
- /* format neighbor callsign */
- if (setcall (neighbor, argv[1]) == -1) {
- tputs ("bad neighbor callsign\n");
- return -1;
- }
- /* find interface */
- if ((ifp = FindNrIface (argv[2])) == NULLIF)
- return -1;
-
- return nr_nfdrop (neighbor, ifp);
- }
-
-
- /* nodefilter mode subcommand */
- static int
- donfmode (int argc, char *argv[], void *p OPTIONAL)
- {
- if (argc < 2) {
- tputs ("filter mode is ");
- switch (Nr_nfmode) {
- case NRNF_NOFILTER:
- tputs ("none\n");
- break;
- case NRNF_ACCEPT:
- tputs ("accept\n");
- break;
- case NRNF_REJECT:
- tputs ("reject\n");
- break;
- default:
- tputs ("some strange, unknown value\n");
- }
- return 0;
- }
- switch (argv[1][0]) {
- case 'n':
- case 'N':
- Nr_nfmode = NRNF_NOFILTER;
- break;
- case 'a':
- case 'A':
- Nr_nfmode = NRNF_ACCEPT;
- break;
- case 'r':
- case 'R':
- Nr_nfmode = NRNF_REJECT;
- break;
- default:
- tputs ("modes are: none accept reject\n");
- return -1;
- }
-
- return 0;
- }
-
-
- /* netrom network packet time-to-live initializer */
- static int
- donrttl (int argc, char *argv[], void *p OPTIONAL)
- {
- return setshort (&Nr_ttl, "Time to live", argc, argv);
- }
-
-
- /* show hidden (ie '#...') nodes or not */
- static int
- donrhidden (int argc, char *argv[], void *p OPTIONAL)
- {
- return setbool (&Nr_hidden, "Hidden nodes", argc, argv);
- }
-
-
- /* allow automatic derating of netrom routes on link failure */
- static int
- donrderate (int argc, char *argv[], void *p OPTIONAL)
- {
- return setbool (&Nr_derate, "Derate flag", argc, argv);
- }
-
-
- /* promiscuous acceptance of broadcasts */
- static int
- donrpromisc (int argc, char *argv[], void *p OPTIONAL)
- {
- return setbool (&Nr_promisc, "Promiscuous flag", argc, argv);
- }
-
-
- #ifdef ALLSESSIONS
- /* Initiate a NET/ROM transport connection */
- static int
- donrconnect (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- struct nrroute_tab *np;
- struct sockaddr_nr lsocket, fsocket;
- char alias[AXBUF];
- struct session *sp;
- int split = 0;
-
- /*Make sure this comes from console - WG7J*/
- if (Curproc->input != Command->input)
- return 0;
-
- #ifdef ALLSERV
- if (argv[0][0] == 's')
- split = 1;
- #endif
-
- /* Get a session descriptor */
- if ((sp = newsession (argv[1], NRSESSION, split)) == NULLSESSION) {
- tputs (TooManySessions);
- return 1;
- }
- if ((sp->s = socket (AF_NETROM, SOCK_SEQPACKET, 0)) == -1) {
- tputs (Nosock);
- (void) keywait (NULLCHAR, 1);
- freesession (sp);
- return 1;
- }
- /* See if the requested destination is a known alias or call,
- * use it if it is. Otherwize give an error message. - WG7J
- */
- (void) putalias (alias, argv[1], 0);
- (void) strupr (argv[1]); /*make sure it's upper case*/
- if ((np = find_nrboth (alias, argv[1])) == NULLNRRTAB) {
- /*no such call or node alias*/
- tputs ("no such node\n\n");
- (void) keywait (NULLCHAR, 1);
- freesession (sp);
- return 1;
- }
- /* Setup the local side of the connection */
- lsocket.nr_family = AF_NETROM;
-
- /* Set up our local username, bind would use Mycall instead */
- memcpy (lsocket.nr_addr.user, Nr4user, AXALEN);
-
- /* Putting anything else than Nr_iface->hwaddr here will not work ! */
- memcpy (lsocket.nr_addr.node, Nr_iface->hwaddr, AXALEN);
-
- /* Now bind the socket to this */
- (void) bind (sp->s, (char *) &lsocket, sizeof (struct sockaddr_nr));
-
-
- /* Set up the remote side of the connection */
- fsocket.nr_family = AF_NETROM;
- memcpy (fsocket.nr_addr.user, np->call, AXALEN);
- memcpy (fsocket.nr_addr.node, np->call, AXALEN);
- fsocket.nr_family = AF_NETROM;
-
- return tel_connect (sp, (char *) &fsocket, sizeof (struct sockaddr_nr));
- }
-
- #endif
-
-
- /* Reset a net/rom connection abruptly */
- static int
- donrreset (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- struct nr4cb *cb;
-
- cb = (struct nr4cb *) htoi (argv[1]);
- if (!nr4valcb (cb)) {
- tputs (Notval);
- return 1;
- }
- reset_nr4 (cb);
- return 0;
- }
-
-
- /* Force retransmission on a net/rom connection */
-
- static int
- donrkick (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
- {
- struct nr4cb *cb;
-
- cb = (struct nr4cb *) htoi (argv[1]);
- if (kick_nr4 (cb) == -1) {
- tputs (Notval);
- return 1;
- } else
- return 0;
- }
-
-
- /* netrom transport ACK delay timer */
- static int
- donracktime (int argc, char *argv[], void *p OPTIONAL)
- {
- return setlong (&Nr4acktime, "Ack delay time (ms)", argc, argv);
- }
-
-
- /* netrom transport choke timeout */
- static int
- donrchoketime (int argc, char *argv[], void *p OPTIONAL)
- {
- return setlong (&Nr4choketime, "Choke timeout (ms)", argc, argv);
- }
-
-
- /* netrom transport initial round trip time */
-
- static int
- donrirtt (int argc, char *argv[], void *p OPTIONAL)
- {
- return setlong (&Nr4irtt, "Initial RTT (ms)", argc, argv);
- }
-
-
- /* netrom transport receive queue length limit. This is the */
- /* threshhold at which we will CHOKE the sender. */
-
- static int
- donrqlimit (int argc, char *argv[], void *p OPTIONAL)
- {
- return setshort (&Nr4qlimit, "Queue limit (bytes)", argc, argv);
- }
-
-
- /* Display or change our NET/ROM username */
- static int
- donruser (int argc, char *argv[], void *p OPTIONAL)
- {
- char buf[AXBUF];
-
- if (argc < 2) {
- pax25 (buf, Nr4user);
- tprintf ("%s\n", buf);
- return 0;
- }
- if (setcall (Nr4user, argv[1]) == -1)
- return -1;
- Nr4user[ALEN] |= E;
- return 0;
- }
-
-
- /* netrom transport maximum window. This is the largest send and */
- /* receive window we may negotiate */
-
- static int
- donrwindow (int argc, char *argv[], void *p OPTIONAL)
- {
- return setshort (&Nr4window, "Window (frames)", argc, argv);
- }
-
-
- /* netrom transport maximum retries. This is used in connect and */
- /* disconnect attempts; I haven't decided what to do about actual */
- /* data retries yet. */
-
- static int
- donrretries (int argc, char *argv[], void *p OPTIONAL)
- {
- return setshort (&Nr4retries, "Retry limit", argc, argv);
- }
-
-
- /* Display the status of NET/ROM connections */
-
- int
- donrstatus (int argc, char *argv[], void *p OPTIONAL)
- {
- int i;
- struct nr4cb *cb;
- char luser[AXBUF], ruser[AXBUF], node[AXBUF];
-
- if (argc < 2) {
- #ifdef UNIX
- tputs ("&NCB Snd-W Snd-Q Rcv-Q LUser RUser @Node State\n");
- #else
- tputs ("&NCB Snd-W Snd-Q Rcv-Q LUser RUser @Node State\n");
- #endif
- for (i = 0; i < NR4MAXCIRC; i++) {
- if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
- continue;
- pax25 (luser, cb->local.user);
- pax25 (ruser, cb->remote.user);
- pax25 (node, cb->remote.node);
- #ifdef UNIX
- if (tprintf ("%8.8lx %3d %5d %5d %9s %9s %-9s %s\n",
- #else
- if (tprintf ("%4.4x %3d %5d %5d %9s %9s %-9s %s\n",
- #endif
- (uint32) cb, cb->nbuffered, len_q (cb->txq),
- len_p (cb->rxq), luser, ruser, node,
- Nr4states[cb->state]) == EOF)
- break;
- }
- return 0;
- }
- cb = (struct nr4cb *) htoi (argv[1]);
- if (!nr4valcb (cb)) {
- tputs (Notval);
- return 1;
- }
- donrdump (cb);
- return 0;
- }
-
-
- /* Dump one control block */
-
- void
- donrdump (struct nr4cb *cb)
- {
- char luser[AXBUF], ruser[AXBUF], node[AXBUF];
- unsigned seq;
- struct nr4txbuf *b;
- struct timer *t;
-
- pax25 (luser, cb->local.user);
- pax25 (ruser, cb->remote.user);
- pax25 (node, cb->remote.node);
-
- tprintf ("Local: %s %d/%d Remote: %s @ %s %d/%d State: %s\n",
- luser, cb->mynum, cb->myid, ruser, node,
- cb->yournum, cb->yourid, Nr4states[cb->state]);
-
- tprintf ("Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %s\n",
- cb->window, uchar (cb->rxpected), uchar (cb->rxpastwin),
- len_p (cb->rxq), cb->qfull ? "RxCHOKED" : "");
-
- tprintf (" Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %s\n",
- cb->nbuffered, uchar (cb->ackxpected), uchar (cb->nextosend),
- len_q (cb->txq), cb->choked ? "TxCHOKED" : "");
-
- tputs ("TACK: ");
- if (run_timer (&cb->tack))
- tprintf ("%lu", read_timer (&cb->tack));
- else
- tputs ("stop");
- tprintf ("/%lu ms; ", dur_timer (&cb->tack));
-
- tputs ("TChoke: ");
- if (run_timer (&cb->tchoke))
- tprintf ("%lu", read_timer (&cb->tchoke));
- else
- tputs ("stop");
- tprintf ("/%lu ms; ", dur_timer (&cb->tchoke));
-
- tputs ("TCD: ");
- if (run_timer (&cb->tcd))
- tprintf ("%lu", read_timer (&cb->tcd));
- else
- #ifndef NR4TDISC
- tputs ("stop");
- tprintf ("/%lu ms", dur_timer (&cb->tcd));
- #else
- tputs ("stop");
- tprintf ("/%lu ms; ", dur_timer (&cb->tcd));
-
- tputs ("TDisc: ");
- if (run_timer (&cb->tdisc))
- tprintf ("%lu", (read_timer (&cb->tdisc) / 1000L));
- else
- tputs ("stop");
- tprintf ("/%lu", (dur_timer (&cb->tdisc) / 1000L));
- #endif
-
- if (run_timer (&cb->tcd))
- tprintf ("; Tries: %u\n", cb->cdtries);
- else
- tputc ('\n');
-
- tprintf ("Backoff Level %u SRTT %ld ms Mean dev %ld ms\n",
- cb->blevel, cb->srtt, cb->mdev);
-
- /* If we are connected and the send window is open, display */
- /* the status of all the buffers and their timers */
-
- if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
-
- tputs ("TxBuffers: Seq Size Tries Timer\n");
-
- for (seq = cb->ackxpected;
- nr4between ((unsigned) cb->ackxpected, seq, (unsigned) cb->nextosend);
- seq = (seq + 1) & NR4SEQMASK) {
-
- b = &cb->txbufs[seq % cb->window];
- t = &b->tretry;
-
- if (tprintf (" %3u %3d %5d %lu/%lu\n",
- seq, len_p (b->data), b->retries + 1,
- read_timer (t), dur_timer (t))
- == EOF)
- break;
- }
-
- }
- }
-
-
- /* netrom timers type - linear v exponential */
- static int
- donrtype (int argc, char *argv[], void *p OPTIONAL)
- {
- if (argc < 2) {
- tprintf ("Netrom timer type is %s\n", Nr_timertype ? "linear" : "exponential");
- return 0;
- }
- switch (argv[1][0]) {
- case 'l':
- case 'L':
- Nr_timertype = 1;
- break;
- case 'e':
- case 'E':
- Nr_timertype = 0;
- break;
- default:
- tputs ("use: netrom timertype [linear|exponential]\n");
- return -1;
- }
-
- return 0;
- }
-
-
- static int
- dominquality (int argc, char *argv[], void *p OPTIONAL)
- {
- unsigned val;
-
- if (argc < 2) {
- tprintf ("%u\n", Nr_autofloor);
- return 0;
- }
- val = (unsigned int) atoi (argv[1]);
-
- if (val == 0 || val > 255) {
- tputs ("The minimum acceptable quality must be 1 to 255\n");
- return 1;
- }
- Nr_autofloor = val;
-
- return 0;
- }
-
-
- /* Fixed and now functional, 920317 WG7J */
- int
- donrload (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- char buff[255];
- FILE *fn;
- time_t now, prev;
- #ifdef notdef
- long t1, t2;
- int j;
- #endif
- int quality, obso;
- int permanent, record;
- struct iface *ifp;
- char alias[12], dest[12], iface[12], neighbor[12], type[3], *ptr;
- char destalias[ALEN + 1]; /*alias in 'alias form'*/
- char destcall[AXALEN]; /*in callsign (ie shifted) form */
- char destneighbor[AXALEN];
-
- if (Nr_iface == NULLIF) {
- tputs ("Attach netrom interface first\n");
- return 1;
- }
- if ((fn = fopen (Netromfile, READ_TEXT)) == NULLFILE) {
- tputs("Can't open netrom save file!\n");
- return 1;
- }
- if (fgets (buff, sizeof (buff), fn) == NULLCHAR) { /* read the timestamp */
- (void) fclose (fn);
- return 1;
- }
- if ((strncmp (buff, "time = ", 7)) != 0) {
- tputs("Wrong node file content\n");
- (void) fclose (fn);
- return 1;
- }
- (void) time (&now);
- sscanf (buff, "time =%ld", &prev);
- if (prev >= now) {
- (void) fclose (fn);
- return 1;
- }
- #ifdef notdef
- t1 = now - prev;
- t2 = dur_timer (&Obsotimer) / 1000L;
- j = t1 / t2; /* recalculate obsolete count */
- tprintf ("%ld seconds are past ( %d obsolete scans)\n", t1, j);
- #endif
-
- while (fgets (buff, sizeof (buff), fn) != NULLCHAR) {
- if ((ptr = strchr (buff, ':')) == 0) {
- sscanf (buff, "%s%s%i%i%s%s"
- ,dest, type, &quality, &obso, iface, neighbor);
- alias[0] = '\0';
- } else {
- *ptr = ' ';
- sscanf (buff, "%s%s%s%i%i%s%s"
- ,alias, dest, type, &quality, &obso, iface, neighbor);
- }
- /*Set and check calls / alias - WG7J */
- if (setcall (destcall, dest) == -1)
- continue;
-
- if (setcall (destneighbor, neighbor) == -1)
- continue;
-
- if (putalias (destalias, alias, 1) == -1)
- continue;
-
- /* find interface */
- if ((ifp = if_lookup (iface)) == NULLIF)
- continue;
-
- /* Is it a netrom interface ? */
- if (!(ifp->flags & IS_NR_IFACE))
- continue;
-
- /* get and check quality value */
- if (quality > 255 || (unsigned) quality < Nr_autofloor)
- continue;
-
- /* Check the type of route - WG7J */
- permanent = record = 0;
- if (strchr (type, 'P') != NULLCHAR)
- permanent = 1;
- else {
- if (strchr (type, 'R') != NULLCHAR)
- record = 1;
- }
- (void) nr_routeadd (destalias, destcall, ifp, (unsigned) quality, destneighbor, \
- (unsigned) permanent, (unsigned) record);
- }
- (void) fclose (fn);
- return 0;
- }
-
-
- int
- donrsave (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- register struct nrroute_tab *rp;
- register struct nr_bind *bp;
- register struct nrnbr_tab *np;
- char neighbor[AXBUF];
- register int i;
- char buf[16];
- char *cp;
- FILE *fn;
- time_t now;
-
- if ((fn = fopen (Netromfile, "w+")) == NULLFILE) {
- tputs ("Can't write netrom save file!\n");
- return 1;
- }
- (void) time (&now);
- fprintf (fn, "time = %ld\n", now);
- for (i = 0; i < NRNUMCHAINS; i++) {
- for (rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next) {
- strncpy (buf, rp->alias, 16);
- /* remove trailing spaces */
- if ((cp = strchr (buf, ' ')) == NULLCHAR)
- cp = &buf[strlen (buf)];
- if (cp != buf) /* don't include colon for null alias */
- *cp++ = ':';
- for (bp = rp->routes; bp != NULLNRBIND; bp = bp->next) {
- pax25 (cp, rp->call);
- fprintf (fn, "%-16s ", buf);
- np = bp->via;
- if (fprintf (fn, "%1s %3d %3d %-8s %s\n",
- (bp->flags & NRB_PERMANENT ? "P" :
- bp->flags & NRB_RECORDED ? "R" : "X"),
- bp->quality, bp->obsocnt,
- np->iface->name,
- pax25 (neighbor, np->call)) == EOF)
- break;
- }
- }
- }
- (void) fclose (fn);
- return 0;
- }
-
- #endif /* NETROM */
-